package cac.common;

import java.util.List;
import java.util.Map;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import cn.hutool.core.util.XmlUtil;

/**
 * @ClassName:  XmlCreateUtil 
 * @Description: xml文件创建工具类 
 *  			一、基于org.w3c.dom，以及Hutool的XML工具XmlUtil，
 * 				二、JDK目前已经封装有XML解析和构建工具：w3c dom，但是其API操作比较繁琐，Hutool的XmlUtil对w3c dom进行了简单工具化封装
 * 				三、如果XML操作较复杂，依旧推荐使用Dom4j
 * 				四、本工具类创建的xml文档格式：数据库表名→xml文档元素节点，表字段→元素节点属性值。如下所示：
 * 					<root>
 * 						<AIKDocument aoType="AODoc" isKey="1">
 * 							<AIKChanges>
 * 								<AIKChange date="20200611" modifyContent="修订"/>
 * 								<AIKChange date="20200610" modifyContent="新增"/>
 * 							</AIKChanges>
 * 							<AIKsequences>
 * 								<AIKsequence sequenceNum="00" sequenceName="预装"/>
 * 								<AIKsequence sequenceNum="05" sequenceName="准备"/>
 * 							</AIKsequences>
 * 						</AIKsequences>
 * 					</root>	
 * 				五：该工具类使用方式：
 * 					1、构造xml文档，new XmlCreateUtil("root");
 * 					2、将数据库查询出来的表数据，写入xml文档中，createElementChildNode(element,nodeName,paramList);
 * 					3、将xml文档内容写入xml文件中，writeToFile(filePath);
 * @author: 杨铁军
 * @date:   2022年9月18日 下午5:46:57
 * @Copyright: 
 */
public class XmlCreateUtil {

	// XML文档对象
	private Document doc;
	
	// XML文档元素节点的根节点对象
	public Element rootElement;
	
	/**
	 * @Title: XmlCreateUtil
	 * @Description: 创建xml文档  
	 * @param: rootElementName，xml文档根节点元素名，默认为root
	 * @param: 返回创建好的xml文件根节点元素      
	 * @return: Element      
	 * @throws 
	 */
	public XmlCreateUtil(String rootElementName) {

		if ("".equals(rootElementName)||rootElementName==null) {
			rootElementName = "root";
		}
		
		// hutool的XmlUtil创建的XML默认是utf8编码
		this.doc = XmlUtil.createXml(rootElementName);
		
		this.rootElement = XmlUtil.getRootElement(this.doc);	
	}
	
	
	/**
	 * @Title: createRootChildNode
	 * @Description: 在根节点下创建一个子节点，并添加属性值  
	 * @param: nodeName 要创建的子节点名   
	 * @return: Element      
	 * @throws 
	 */
	public Element createRootChildNode(String nodeName,Map<String,Object> paramMap) {
		
		// 创建子节点
		Element rootChildNode = this.doc.createElement(nodeName);
		
		// 添加属性值
		if (paramMap!=null) {
			for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
				String key = entry.getKey();
				String value = String.valueOf(entry.getValue());
				
				value = attributeValueHandle(value);
				
				rootChildNode.setAttribute(key, value);
			}			
		}
		
		// 将子节点放在根节点节点下
		this.rootElement.appendChild(rootChildNode);	
		
		return rootChildNode;			
	}
	
	
	/**
	 * @Title: createElementChildNodes
	 * @Description: 将查询出来的数据库数据写入xml指定节点下  
	 * @param: @param element 指定的父节点
	 * @param: @param nodeName 每条数据创建的同名元素节点
	 * @param: @param paramList 数据库数据List     
	 * @return: void      
	 * @throws 
	 */
	public void createElementChildNodes(Element element,String nodeName,List<Map<String,Object>> paramList) {
		
		if (paramList != null) {
			for (Map<String,Object> tempMap: paramList) {
				createElementChildNode(element,nodeName,tempMap);
			}
		}
	}
	
	/**
	 * @Title: createElementChildNode
	 * @Description: 在指定的元素节点下创建一个子节点，并添加属性值
	 * @param: element 指定的元素节点
	 * @param: nodeName 要创建的子节点名   
	 * @return: Element      
	 * @throws 
	 */
	public Element createElementChildNode(Element element,String nodeName,Map<String,Object> paramMap) {
		
		// 创建子节点
		Element childNode = this.doc.createElement(nodeName);
		
		// 添加属性值
		if (paramMap!=null) {
			for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
				String key = entry.getKey();
				String value = String.valueOf(entry.getValue());							
				
				value = attributeValueHandle(value);
				
				childNode.setAttribute(key, value);
			}			
		}
		
		// 将子节点放在父节点下
		element.appendChild(childNode);
		
		return childNode;			
	}
	
	
	/**
	 * @Title: attributeValueHandle
	 * @Description: 针对数据库数据在Java中的处理  
	 * @param:  attributeValue     
	 * @return: String      
	 * @throws 
	 */
	private String attributeValueHandle(String attributeValue) {
		
		// 针对数据库数据，null字符串转为空
		if ("null".equals(attributeValue)) {
			attributeValue = "";
		}
		
		// 避免和xml文档本身的标签<>冲突，如果数据库的数据有<>，转为&lt;和&gt;
		attributeValue = attributeValue.replace("<", "&lt;").replace(">", "&gt;").replace("/t", "");
		
		return attributeValue;
	}
	
	/**
	 * @Title: writeToFile
	 * @Description: 将xml内容写到指定文件中
	 * @param: FilePath 指定的xml文件绝对路径 ，如：D:\\Test\\test.xml
	 * @return: void      
	 * @throws 
	 */
	public void writeToFile(String FilePath) {
		XmlUtil.toFile(this.doc, FilePath);
	}
	
}
